package com.efrei.schoolmanager.model.hibernate;

import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;

import com.efrei.schoolmanager.exceptions.LogicException;
import com.efrei.schoolmanager.model.obj.Classe;
import com.efrei.schoolmanager.model.obj.Eleve;
import com.efrei.schoolmanager.model.obj.Enseignant;
import com.efrei.schoolmanager.model.obj.Etablissement;
import com.efrei.schoolmanager.model.obj.Matiere;
import com.efrei.schoolmanager.model.obj.Medecin;
import com.efrei.schoolmanager.model.obj.Niveau;
import com.efrei.schoolmanager.model.obj.Note;
import com.efrei.schoolmanager.model.obj.Pays;
import com.efrei.schoolmanager.model.obj.Responsable;
import com.efrei.schoolmanager.model.obj.Ville;

/**
 * classe centrale pour gestion des sessions
 */
public class HibernateUtil {
	private static ServiceRegistry serviceRegistry = null;
	private static SessionFactory sessionFactory = null;

	public static SessionFactory configureSessionFactory()
			throws HibernateException, LogicException {
		/*
		 * ajout du fichier de configuration de hibernate ET des mappings des
		 * classes métiers Note: donner une classe à addClass nous evite
		 * d'ecrire des packages en dur
		 */
		Configuration cfg = new Configuration()
				.addResource("hibernate.cfg.xml")
				// sans dépendances
				.addClass(Pays.class)
				.addClass(Niveau.class)
				.addClass(Matiere.class)
				// par niveau de dépendances
				// dépendances niveau 1
				.addClass(Ville.class).addClass(Classe.class)
				// dépendances niveau 2
				.addClass(Medecin.class).addClass(Enseignant.class)
				.addClass(Etablissement.class).addClass(Responsable.class)
				// dépendances niveau 3
				.addClass(Eleve.class)
				// dépendances niveau 4
				.addClass(Note.class);
		cfg.configure();

		// enregistrera nos services
		serviceRegistry = new ServiceRegistryBuilder().applySettings(
				cfg.getProperties()).buildServiceRegistry();
		// création de la Factory de session (et connexion à la base)
		sessionFactory = cfg.buildSessionFactory(serviceRegistry);
		System.out
				.println("HibernateUtil: sessionFactory activé, test connexion");

		testConnection();

		return sessionFactory;
	}

	private static void testConnection() throws LogicException {
		try {
			Transaction tx = getSession().beginTransaction();
			if (!getSession().isConnected())
				throw new LogicException("La connection a la base a échoué");
			tx.rollback();
		} catch (HibernateException e) {
			e.printStackTrace();
			throw new LogicException(e.getMessage());
		}
	}

	/**
	 * @return session factory qui va ouvrir les sessions
	 * @throws LogicException
	 * @throws HibernateException
	 */
	public static SessionFactory getSessionFactory() throws HibernateException,
			LogicException {
		if (sessionFactory == null)
			sessionFactory = HibernateUtil.configureSessionFactory();
		return sessionFactory;
	}

	/**
	 * @return l'actuel session de travail OU une nouvelle si aucune trouvée
	 * @throws LogicException
	 * @throws HibernateException
	 */
	public static Session getSession() throws HibernateException,
			LogicException {
		return getSessionFactory().getCurrentSession();
	}
}
